#include "StdAfx.h"
#include "Kernel32.h"

using namespace Adaptive::Foundation;
using namespace Adaptive::Win32;

/*--------------------------------------------------------------------------------
 * Constructor / Dispose / Destructor Methods
 *------------------------------------------------------------------------------*/
#pragma region Constructor / Dispose / Destructor Methods
// <summary>
// Initializes a new instance of the class.
// </summary>
// <remarks>
// This is the default constructor.
// </remarks>
Kernel32::Kernel32()
{
}
#pragma endregion

/*--------------------------------------------------------------------------------
 * Public Methods / Functions
 *------------------------------------------------------------------------------*/
#pragma region Public Methods / Functions
// <summary>
// Closes an open object handle.
// </summary>
// <remarks>
// This is used to safely close an operating system handle value.
// </remarks>
// <param name="handleToClose">An <see cref="IntPtr"/> represneting the handle to be closed.</param>
void Kernel32::CloseHandle(IntPtr handleToClose)
{
	if (handleToClose != IntPtr::Zero)
		::CloseHandle((HANDLE)handleToClose.ToInt32());
}
// <summary>
// Opens a file or device for read and write access.
// </summary>
// <remarks>
// This uses the system CreateFile() api for opening I/O to a file or device.
// </remarks>
// <param name="fileName">A string indicating the name of the file or name of the device to open.</param>
// <param name="mode">The desired file access mode.</param>
// <returns>
// If successful, returns a <see cref="BasicSafeHandle"/> instance containing the system handle to 
// the opened object instance; otherwise, returns <b>null</b>.
// </returns>
BasicSafeHandle^ Kernel32::CreateFileAccess(String^ fileName, FileMode mode)
{
	return CreateFileAccess(fileName, mode, DesiredAccessRights::GenericRead | DesiredAccessRights::GenericWrite , 
		FileShare::ReadWrite, (FileAccessAttributeOptions)0);
}
// <summary>
// Opens a file or device for read and write access.
// </summary>
// <remarks>
// This uses the system CreateFile() api for opening I/O to a file or device.
// </remarks>
// <param name="fileName">A string indicating the name of the file or name of the device to open.</param>
// <param name="mode">The desired file access mode.</param>
// <param name="desiredAccess">A <see cref="DesiredAccessRights"/> enumeration indicating the desired access rights.</param>
// <returns>
// If successful, returns a <see cref="BasicSafeHandle"/> instance containing the system handle to 
// the opened object instance; otherwise, returns <b>null</b>.
// </returns>
BasicSafeHandle^ Kernel32::CreateFileAccess(String^ fileName, FileMode mode, DesiredAccessRights desiredAccess)
{
	return CreateFileAccess(fileName, mode, desiredAccess, FileShare::ReadWrite, (FileAccessAttributeOptions)0);
}
// <summary>
// Opens a file or device for read and write access.
// </summary>
// <remarks>
// This uses the system CreateFile() api for opening I/O to a file or device.
// </remarks>
// <param name="fileName">A string indicating the name of the file or name of the device to open.</param>
// <param name="mode">The desired file access mode.</param>
// <param name="desiredAccess">A <see cref="DesiredAccessRights"/> enumeration indicating the desired access rights.</param>
// <param name="shareMode">The desired file sharing mode.</param>
// <returns>
// If successful, returns a <see cref="BasicSafeHandle"/> instance containing the system handle to 
// the opened object instance; otherwise, returns <b>null</b>.
// </returns>
BasicSafeHandle^ Kernel32::CreateFileAccess(String^ fileName, FileMode mode, DesiredAccessRights desiredAccess, FileShare shareMode)
{
	return CreateFileAccess(fileName, mode, desiredAccess, shareMode, (FileAccessAttributeOptions)0);
}
// <summary>
// Opens a file or device for read and write access.
// </summary>
// <remarks>
// This uses the system CreateFile() api for opening I/O to a file or device.
// </remarks>
// <param name="fileName">A string indicating the name of the file or name of the device to open.</param>
// <param name="mode">The desired file access mode.</param>
// <param name="desiredAccess">A <see cref="DesiredAccessRights"/> enumeration indicating the desired access rights.</param>
// <param name="shareMode">The desired file sharing mode.</param>
// <param name="fileOptions">A <see cref="FileAccessAttributeOptions"/> enumeration indicating the file attribute access
// desired.</param>
// <returns>
// If successful, returns a <see cref="BasicSafeHandle"/> instance containing the system handle to 
// the opened object instance; otherwise, returns <b>null</b>.
// </returns>
BasicSafeHandle^ Kernel32::CreateFileAccess(String^ fileName, FileMode mode, DesiredAccessRights desiredAccess, FileShare shareMode, 
							FileAccessAttributeOptions fileOptions)
{
	CString nameOfFileOrDevice = fileName;
	HANDLE newFileHandle = NULL;
	DWORD creationDisposition = 0;
	DWORD shareModeValue = 0;
	IntPtr^ returnHandle = IntPtr::Zero;
	BasicSafeHandle^ returnValue = nullptr;

	switch(shareMode)
	{
	case FileShare::Delete:
		shareModeValue = FILE_SHARE_DELETE;
		break;

	case FileShare::None:
		shareModeValue = 0;
		break;

	case FileShare::Read:
		shareModeValue = FILE_SHARE_READ;
		break;

	case FileShare::ReadWrite:
		shareModeValue = FILE_SHARE_WRITE | FILE_SHARE_READ;
		break;

	case FileShare::Write:
		shareModeValue = FILE_SHARE_WRITE;
		break;

	}
	switch(mode)
	{
	case FileMode::Append:
		creationDisposition = OPEN_EXISTING;
		break;

	case FileMode::Create:
		creationDisposition = CREATE_NEW | OPEN_EXISTING;
		break;

	case FileMode::CreateNew:
		creationDisposition = CREATE_ALWAYS;
		break;

	case FileMode::Open:
		creationDisposition = OPEN_EXISTING;
		break;

	case FileMode::OpenOrCreate:
		creationDisposition = OPEN_ALWAYS;
		break;

	case FileMode::Truncate:
		creationDisposition = TRUNCATE_EXISTING;
		break;
	}

	newFileHandle = ::CreateFile(nameOfFileOrDevice, 
								 (DWORD)desiredAccess,
								 shareModeValue,
								 NULL, creationDisposition,
								 (DWORD)fileOptions, NULL);

	if ((newFileHandle != NULL) && (newFileHandle  != INVALID_HANDLE_VALUE))
	{
		returnHandle = gcnew IntPtr((int)newFileHandle);
		returnValue = gcnew BasicSafeHandle(returnHandle);
	}
				 
	return returnValue;

}
// <summary>
// Duplicates an object handle.
// </summary>
// <remarks>
// The duplicate handle refers to the same object as the original handle.  Therefore, any changes to the object are reflected 
// through both handles.
// </remarks>
// <param name="sourceHandle">An <see cref="IntPtr"/> containing the handle to be duplicated.</param>
// <returns>
// A new <see cref="IntPtr"/> with the duplicated handle, or <see cref="IntPtr.Zero"/> if not successful.
// </returns>
IntPtr Kernel32::DuplicateHandle(IntPtr sourceHandle)
{
	BOOL	result = FALSE;
	HANDLE	processHandle = NULL;
	HANDLE	targetHandle = NULL;
	DWORD	desiredAccess = 0;
	DWORD	options = DUPLICATE_SAME_ACCESS;
	BOOL	inheritHandle = FALSE;
	IntPtr	returnValue = IntPtr::Zero;

	processHandle = ::GetCurrentProcess();

	result = ::DuplicateHandle(processHandle, (HANDLE)sourceHandle.ToInt32(), processHandle, &targetHandle, desiredAccess, inheritHandle, options);
	if (result)
		returnValue = (IntPtr)targetHandle;

	return returnValue;
}
// <summary>
// Duplicates an object handle.
// </summary>
// <remarks>
// The duplicate handle refers to the same object as the original handle.  Therefore, any changes to the object are reflected 
// through both handles.
// </remarks>
// <param name="sourceHandle">An <see cref="IntPtr"/> containing the handle to be duplicated.</param>
// <param name="options">An <see cref="DuplicateHandleOptions"/> value specifying the access requested for the new handle.</param>
// <param name="inheritHandle">A value indicating whether to handle is inheritable.</param>
// <returns>
// A new <see cref="IntPtr"/> with the duplicated handle, or <see cref="IntPtr.Zero"/> if not successful.
// </returns>
IntPtr Kernel32::DuplicateHandle(IntPtr sourceHandle, DuplicateHandleOptions options, bool inheritHandle)
{
	BOOL	result = FALSE;
	HANDLE	processHandle = NULL;
	HANDLE	targetHandle = NULL;
	DWORD	desiredAccess = 0;
	IntPtr	returnValue = IntPtr::Zero;

	processHandle = ::GetCurrentProcess();

	result = ::DuplicateHandle(processHandle, (HANDLE)sourceHandle.ToInt32(), processHandle, &targetHandle, desiredAccess, 
		inheritHandle, (DWORD)options);
	if (result)
		returnValue = (IntPtr)targetHandle;

	return returnValue;
}
// <summary>
// Retrieves certain properties of an object handle.,
// </summary>
// <param name="itemHandle">An <see cref="IntPtr"/> containing the handle for which information is to
// be retrieved.</param>
// <returns>
// A <see cref="BitArray"/> instance containing the bit flags returned by the system.
// </returns>
BitArray^ Kernel32::GetHandleInformation(IntPtr itemHandle)
{
	DWORD flagsValues = NULL;
	BOOL result = FALSE;
	BitArray^ returnValue = nullptr;
	array<int>^ valuesList = nullptr;

	if (itemHandle != IntPtr::Zero)
	{
		result = ::GetHandleInformation((HANDLE)itemHandle.ToInt32(), &flagsValues);
		if (result)
		{
			valuesList = gcnew array<int>(1);
			valuesList[0] = (int)flagsValues;
			returnValue = gcnew BitArray(valuesList);
			delete(valuesList);
			valuesList = nullptr;
		}

	}
	return returnValue;
}
// <summary>
// Gets the name of the computer.
// </summary>
// <returns>
// The current computer name.
// </returns>
String^	Kernel32::ExtractComputerName()
{
	String^ returnValue = nullptr;
	wchar_t* buffer = NULL;
	DWORD size = 1024;

	buffer = new wchar_t[1024];
	memset(buffer, 0, 1024);

	::GetComputerName(buffer, &size);
	returnValue = gcnew String(buffer);
	delete(buffer);

	return returnValue;
}
// <summary>
// Gets the handle to the current process.
// </summary>
// <returns>
// An <see cref="IntPtr"/> containing the handle to the current process.
// </returns>
IntPtr	Kernel32::GetCurrentProcessHandle()
{
	IntPtr^ returnValue = IntPtr::Zero;
	HANDLE currentProcHandle = NULL;

	currentProcHandle = GetCurrentProcess();
	returnValue = gcnew IntPtr( currentProcHandle );

	return *returnValue;
}
// <summary>
// Gets the handle to the current process heap.
// </summary>
// <returns>
// An <see cref="IntPtr"/> containing the handle to the current process heap.
// </returns>
IntPtr Kernel32::GetCurrentProcessHeap()
{
	HANDLE heapHandle = NULL;
	IntPtr returnValue = IntPtr::Zero;

	heapHandle = ::GetProcessHeap();
	returnValue = IntPtr::IntPtr( heapHandle );
	return returnValue;
}
// <summary>
// Gets the ID of the current process.
// </summary>
// <returns>
// The ID of the current process.
// </returns>
int Kernel32::GetCurrentProcId()
{
	return (int)::GetCurrentProcessId();
}
// <summary>
// Gets the version of Windows the specified process expects to execute on.
// </summary>
// <param name="processId">The ID of the process.</param>
// <returns>
// A <see cref="Version"/> instance containing the version numbers.
// </returns>
Version^ Kernel32::GetExpectedWindowsVersionForProcess(int processId)
{
	Version^ returnValue = nullptr;
	DWORD versionNo = 0;
	WORD* values = NULL;

	versionNo = ::GetProcessVersion((DWORD)processId);
	values = (WORD*)&versionNo;

	returnValue = gcnew Version((int)values[1], (int)values[0], 0, 0);
	return returnValue;
}
// <summary>
// Gets the version of Windows the current process expects to execute on.
// </summary>
// <returns>
// A <see cref="Version"/> instance containing the version numbers.
// </returns>
Version^ Kernel32::GetExpectedWindowsVersionForCurrentProcess()
{
	Version^ returnValue = nullptr;
	DWORD versionNo = 0;
	WORD* values = NULL;

	versionNo = ::GetProcessVersion(0);
	values = (WORD*)&versionNo;

	returnValue = gcnew Version((int)values[1], (int)values[0], 0, 0);
	return returnValue;
}
// <summary>
// Gets the handle to the desktop window.
// <returns>
// An <see cref="IntPtr"/> containing the handle to the desktop window.
// </returns>
IntPtr Kernel32::GetHandleToDesktopWindow()
{
	IntPtr^ returnValue = IntPtr::Zero;
	HANDLE currentProcHandle = NULL;

	currentProcHandle = GetDesktopWindow();
	returnValue = gcnew IntPtr( currentProcHandle );

	return *returnValue;
	return IntPtr::Zero;
}
// <summary>
// Gets the path of the Windows system directory.
// </summary>
// <returns>
// The fully-qualified system path name.
// </returns>
String^ Kernel32::ExtractSystemDirectory()
{
	String^ returnValue = nullptr;
	wchar_t* buffer = NULL;

	buffer = new wchar_t[1024];
	memset(buffer, 0, 1024);

	::GetSystemDirectory(buffer, 1024);
	returnValue = gcnew String(buffer);
	delete(buffer);

	return returnValue;
}
// <summary>
// Gets the handle to the current thread.
// </summary>
// <returns>
// An <see cref="IntPtr"/> containing the handle to the current thread.
// </returns>
IntPtr Kernel32::GetThisThreadHandle()
{
	IntPtr^ returnValue = IntPtr::Zero;
	HANDLE currentProcHandle = NULL;

	currentProcHandle = GetCurrentThread();
	returnValue = gcnew IntPtr( currentProcHandle );

	return *returnValue;
}
// <summary>
// Gets the ID of the current thread.
// </summary>
// <returns>
// The ID of the current thread.
// </returns>
int Kernel32::GetThisThreadId()
{
	return (int)::GetCurrentThreadId();
}
// <summary>
// Gets the path of the Windows temp file directory.
// </summary>
// <returns>
// The fully-qualified temporary file path name.
// </returns>
String^ Kernel32::ExtractTempFileDirectory()
{
	String^ returnValue = nullptr;
	wchar_t* buffer = NULL;

	buffer = new wchar_t[1024];
	memset(buffer, 0, 1024);

	::GetTempPath(1024, buffer);
	returnValue = gcnew String(buffer);
	delete(buffer);

	return returnValue;
}
// <summary>
// Gets the name of the current user.
// </summary>
// <returns>
// The current user name.
// </returns>
String^ Kernel32::ExtractUserName()
{
	String^ returnValue = nullptr;
	wchar_t* buffer = NULL;
	DWORD size = 1024;

	buffer = new wchar_t[1024];
	memset(buffer, 0, 1024);

	::GetUserName(buffer, &size);

	returnValue = gcnew String(buffer);
	delete(buffer);

	return returnValue;
}
// <summary>
// Gets the path of the Windows directory.
// </summary>
// <returns>
// The fully-qualified Windows path name.
// </returns>
String^ Kernel32::ExtractWindowsDirectory()
{
	String^ returnValue = nullptr;
	wchar_t* buffer = NULL;

	buffer = new wchar_t[1024];
	memset(buffer, 0, 1024);

	::GetWindowsDirectory(buffer, 1024);
	returnValue = gcnew String(buffer);
	delete(buffer);

	return returnValue;
}
// <summary>
// Suspends the execution of the current thread for at least the specified interval.
// </summary>
// <remarks>
// This function causes a thread to relinquish the remainder of its time slice and become unrunnable for at least 
// the specified number of milliseconds, after which the thread is ready to run. In particular, if you specify 
// zero milliseconds, the thread will relinquish the remainder of its time slice but remain ready. Note that a ready 
// thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the specified 
// interval elapses.
// 
// Using this method will stop system messing processing for the thread.  This may cause system deadlock for threads
// which utilize system messages (such as windowing threads).
//
// </remarks>
// <param name="milliseconds">Minimum time interval for which execution is to be suspended, in milliseconds.</param>
void Kernel32::Sleep(int milliseconds)
{
	::Sleep((DWORD)milliseconds);
}
// <summary>
// Sets certain properties of an object handle.
// </summary>
// <param name="itemHandle">An <see cref="IntPtr"/> containing the handle for which information is to
// be retrieved.</param>
// <param name="mask">An integer representing the bit flags to be set for the handle.</param>
// <param name="flags">A <see cref="SetHandleOptions"/> enumeration indicating the options for setting the handle flags.</param>
// <returns>
// <b>true</b> if the operation is successful; otherwise, returns <b>false</b>.
// </returns>
bool Kernel32::SetHandleInformation(IntPtr^ itemHandle, int mask, SetHandleOptions flags)
{
	bool returnValue = false;
	BOOL result = FALSE;

	if ((itemHandle != nullptr) && (itemHandle != IntPtr::Zero))
	{
		result = ::SetHandleInformation((HANDLE)itemHandle->ToInt32(), (DWORD)mask, (DWORD)flags);
		if (result)
			returnValue = true;
	}
	return returnValue;
}

HANDLE Kernel32::InternalOpenProcessHandle(int processId)
{
	HANDLE returnValue = NULL;

	returnValue = OpenProcess(PROCESS_QUERY_INFORMATION, false, processId);
	if (returnValue == NULL)
		throw gcnew Win32Exception(GetLastError());

	return returnValue;
}
HANDLE Kernel32::InternalOpenThreadHandle(int threadId)
{
	HANDLE returnValue = NULL;

	returnValue = OpenThread(THREAD_QUERY_INFORMATION , false, threadId);
	if (returnValue == NULL)
		throw gcnew Win32Exception(GetLastError());

	return returnValue;
}
IntPtr Kernel32::OpenProcessHandle(int processId)
{
	IntPtr returnValue = IntPtr::Zero;

	returnValue = IntPtr::IntPtr( InternalOpenProcessHandle(processId) );
	return returnValue;
}
IntPtr Kernel32::OpenProcessHandle(System::Diagnostics::Process ^process)
{
	IntPtr returnValue = IntPtr::Zero;

	if (process != nullptr)
	{
		returnValue = IntPtr::IntPtr( InternalOpenProcessHandle(process->Id) );
	}
	return returnValue;
}

String^ Kernel32::GetProcessCommandLine()
{
	LPTSTR result = NULL;
	String^ returnValue = nullptr;

	result = ::GetCommandLineW();
	returnValue = gcnew String (result);
	return returnValue;
}

int Kernel32::GetExitCodeForProcess(int processId)
{
	HANDLE processHandle = NULL;
	int returnValue = 0;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		::GetExitCodeProcess(processHandle, (DWORD*)&returnValue);
		::CloseHandle(processHandle);
	}
	return returnValue;
}
int Kernel32::GetExitCodeForProcess(System::Diagnostics::Process^ process)
{
	int returnValue = 0;

	if (process != nullptr)
		returnValue = GetExitCodeForProcess(process->Id);
	return returnValue;
}
int Kernel32::GetExitCodeForThread(int threadId) 
{
	HANDLE threadHandle = NULL;
	int returnValue = 0;

	threadHandle = InternalOpenThreadHandle(threadId);
	if (threadHandle == NULL)
	{
		::GetExitCodeThread(threadHandle, (DWORD*)returnValue);
		::CloseHandle(threadHandle);
	}
	return returnValue;
}
int Kernel32::GetGdiHandleCount(int processId)
{
	HANDLE processHandle = NULL;
	int returnValue = 0;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		returnValue = ::GetGuiResources(processHandle, GR_GDIOBJECTS);
		::CloseHandle(processHandle);
	}
	return returnValue;

}
int Kernel32::GetUserHandleCount(int processId)
{
	HANDLE processHandle = NULL;
	int returnValue = 0;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		returnValue = ::GetGuiResources(processHandle, GR_USEROBJECTS);
		::CloseHandle(processHandle);
	}
	return returnValue;

}
int Kernel32::GetGuiHandleCount(int processId)
{
	HANDLE processHandle = NULL;
	int returnValue = 0;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		returnValue = ::GetGuiResources(processHandle, GR_GDIOBJECTS);
		returnValue += ::GetGuiResources(processHandle, GR_USEROBJECTS);

		::CloseHandle(processHandle);
	}
	return returnValue;

}
int Kernel32::GetGdiHandleCount(System::Diagnostics::Process^ process)
{
	int returnValue = 0;

	if (process != nullptr)
		returnValue = GetGdiHandleCount(process->Id);
	return returnValue;
}int Kernel32::GetUserHandleCount(System::Diagnostics::Process^ process)
{
	int returnValue = 0;

	if (process != nullptr)
		returnValue = GetUserHandleCount(process->Id);
	return returnValue;
}int Kernel32::GetGuiHandleCount(System::Diagnostics::Process^ process)
{
	int returnValue = 0;

	if (process != nullptr)
		returnValue = GetGuiHandleCount(process->Id);
	return returnValue;
}

IoCounters Kernel32::GetProcessIoCounters(int processId)
{
	IoCounters returnValue;
	IO_COUNTERS* counters = NULL;

	HANDLE processHandle = NULL;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		counters = new IO_COUNTERS();
		::GetProcessIoCounters(processHandle, counters);
		::CloseHandle(processHandle);

		if (counters != NULL)
		{
			returnValue.ReadOperationCount = counters->ReadOperationCount;
			returnValue.WriteOperationCount = counters->WriteOperationCount;
			returnValue.OtherOperationCount = counters->OtherOperationCount;
			returnValue.ReadTransferCount = counters->ReadTransferCount;
			returnValue.WriteTransferCount = counters->WriteTransferCount;
			returnValue.OtherTransferCount = counters->OtherTransferCount;	
		}
		delete(counters);
	}
	return returnValue;
}
IoCounters Kernel32::GetProcessIoCounters(System::Diagnostics::Process^ process)
{
	IoCounters returnValue;

	if (process != nullptr)
	{
		returnValue = GetProcessIoCounters(process->Id);
	}

	return returnValue;

}

ProcessShutdownParameters Kernel32::GetProcessShutdownInfo(int processId)
{
	ProcessShutdownParameters returnValue;
	DWORD level = 0;
	DWORD flags = 0;
	HANDLE processHandle = NULL;
	BOOL result = FALSE;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		result = ::GetProcessShutdownParameters(&level, &flags);
		::CloseHandle(processHandle);

		if (result)
		{
			if (level < 0x0FF)
				returnValue.When = ShutdownTiming::SystemLastShutdown;
			else if (level < 0x1FF)
				returnValue.When = ShutdownTiming::ApplicationLastShutdown;
			else if (level < 0x2FF)
				returnValue.When = ShutdownTiming::ApplicationInBetweenShutdown;
			else if (level < 0x3FF)
				returnValue.When = ShutdownTiming::AppplicationFirstShutdown;
			else
				returnValue.When = ShutdownTiming::SystemReserved;

			returnValue.NoRetry = (flags > 0);
		}
	}
	return returnValue;
}
bool Kernel32::SetProcessShutdownInfo(ShutdownTiming timing, bool noRetry)
{
	BOOL result = FALSE;

	result = ::SetProcessShutdownParameters((DWORD)((int)timing * 0x100), (BOOL)noRetry);
	return (result > 0);
}
ProcessShutdownParameters Kernel32::GetProcessShutdownInfo(System::Diagnostics::Process^ process)
{
	if (process != nullptr)
		return GetProcessShutdownInfo(process->Id);
	else
		return *(gcnew ProcessShutdownParameters());
}

ProcessTimes Kernel32::GetProcessProcessTimes(int processId)
{
	System::Runtime::InteropServices::ComTypes::FILETIME* createTime = NULL;
	System::Runtime::InteropServices::ComTypes::FILETIME* exitTime = NULL;
	System::Runtime::InteropServices::ComTypes::FILETIME* kernelTime = NULL;
	System::Runtime::InteropServices::ComTypes::FILETIME* userTime = NULL;
	HANDLE processHandle = NULL;
	ProcessTimes returnValue;

	processHandle = InternalOpenProcessHandle(processId);
	if (processHandle != NULL)
	{
		createTime = new System::Runtime::InteropServices::ComTypes::FILETIME();
		exitTime = new System::Runtime::InteropServices::ComTypes::FILETIME();
		kernelTime = new System::Runtime::InteropServices::ComTypes::FILETIME();
		userTime = new System::Runtime::InteropServices::ComTypes::FILETIME();
		::GetProcessTimes((LPFILETIME)processHandle, (LPFILETIME)createTime, (LPFILETIME)exitTime, (LPFILETIME)kernelTime, (LPFILETIME)userTime);
		::CloseHandle(processHandle);

		//Copy
		returnValue.CreationTime = DateTime::FromFileTime(*((__int64*)createTime));
		returnValue.ExitTime = DateTime::FromFileTime(*((__int64*)exitTime));
		returnValue.KernelTime = TimeSpan::FromTicks(*((__int64*)kernelTime));
		returnValue.UserTime = TimeSpan::FromTicks(*((__int64*)userTime));

		delete(createTime);
		delete(exitTime);
		delete(kernelTime);
		delete(userTime);
	}
	return returnValue;
}
ProcessTimes Kernel32::GetProcessProcessTimes(System::Diagnostics::Process^ process)
{
	if (process != nullptr)
		return GetProcessProcessTimes(process->Id);
	else
		return *(gcnew ProcessTimes());
}
int Kernel32::GetProcessVersion(int processId)
{
	return ::GetProcessVersion(processId);
}
int Kernel32::GetProcessVersion(System::Diagnostics::Process^ process)
{
	if (process != nullptr)
		return ::GetProcessVersion(process->Id);
	else
		return 0;
}

void Kernel32::TerminateProcess(int processId)
{
	HANDLE processHandle = NULL;

	processHandle = OpenProcess(PROCESS_TERMINATE , false, processId);
	if (processHandle != NULL)
	{
		::TerminateProcess(processHandle, 0);
		::CloseHandle(processHandle);
	}
}
void Kernel32::TerminateProcess(System::Diagnostics::Process^ process)
{
	if (process != nullptr)
		TerminateProcess(process->Id);
}
void Kernel32::TerminateThread(int threadId)
{
	HANDLE threadHandle = NULL;

	threadHandle = OpenProcess(THREAD_TERMINATE , false, threadId);
	if (threadHandle != NULL)
	{
		::TerminateThread(threadHandle, 0);
		::CloseHandle(threadHandle);
	}
}

void Kernel32::SystemSleep(int milliseconds)
{
	::Sleep(milliseconds);
}
void Kernel32::SystemSleep(int milliseconds, bool alertable)
{
	::SleepEx(milliseconds, (BOOL)alertable);
}

void Kernel32::WaitForInputIdle(int processId, int milliseconds)
{
	HANDLE processHandle = NULL;

	processHandle = OpenProcess(PROCESS_TERMINATE , false, processId);
	if (processHandle != NULL)
	{
		::WaitForInputIdle(processHandle, (DWORD)milliseconds);
		::CloseHandle(processHandle);
	}

}
void Kernel32::WaitForInputIdle(System::Diagnostics::Process^ process, int milliseconds)
{
	if (process != nullptr)
		WaitForInputIdle(process->Id, milliseconds);
}

/// <summary>
/// Converts the MS-DOS date value to a file-time value.
/// </summary>
/// <param name="dateValue">
/// A <see cref="MsDosDate"/> instance containing the values.
/// </param>
/// <returns>
/// The file-time value used to construct a system timne value.
/// </returns>
/// <exception cref="Win32Exception">
/// Occurs if the underlying platform method fails (returns zero).
/// </exception>
Int64 Kernel32::DosDateToFileTime(MsDosDate^ dateValue)
{
	WORD fatDate = 0;							//Date value container variable.
	WORD fatTime = 0;							//Time value container variable.
	_FILETIME* fileTimeStruct;					//FILETIME structure.
	Int64 returnValue = 0;						//Return value.
	long result = 0;							//Win32 result.
	
		fatDate = (WORD)dateValue->Date;
		fatTime = (WORD)dateValue->Time;

		try
		{
			fileTimeStruct = new _FILETIME();
			result = DosDateTimeToFileTime(fatDate, fatTime, (LPFILETIME)fileTimeStruct);
		}
		catch (Exception^ ex)
		{
			result = 0;
		}

		if (result == 0)
			throw gcnew Win32Exception(GetLastError());
		
		memcpy(&returnValue, fileTimeStruct, 8);
		return returnValue;
}
/// <summary>
/// Converts the specified file-time value to MS-DOS date and time values.
/// </summary>
/// <param name="fileTime">
/// The file time value to be converted.
/// </param>
/// <returns>
/// An <see cref="MsDosDate"/> structure containing the results.
/// </returns>
/// <exception cref="Win32Exception">
/// Occurs if the underlying platform method fails (returns zero).
/// </exception>
MsDosDate^ Kernel32::FileTimeToDosDate(Int64 fileTime)
{
	WORD dateValue = 0;					//Date value variable container.
	WORD timeValue = 0;					//Time value variable container.
	long result = 0;					//Result of operation.
	_FILETIME* fileTimeStruct;			//FILETIME structure.
	MsDosDate^ returnValue;				//Return value.
	
	try
	{
		fileTimeStruct = new _FILETIME();
		memcpy(fileTimeStruct, &fileTime, 8);
		result = FileTimeToDosDateTime(fileTimeStruct, &dateValue, &timeValue);
	}
	catch (Exception^ ex)
	{
		result = 0;
	}
	
	if (result == 0)
		throw gcnew Win32Exception(GetLastError());

	returnValue = gcnew MsDosDate();
	returnValue->Date = Convert::ToUInt16(dateValue);
	returnValue->Time = Convert::ToUInt16(timeValue);
	
	return returnValue;
}
MsDosDate^ Kernel32::DateTimeToDosDate(DateTime dateValue)
{
	return FileTimeToDosDate(dateValue.ToFileTime());
}
#pragma endregion
